/**
  ******************************************************************************
  * @file    controller_can.h
  ******************************************************************************
  */

#ifndef __CONTROLLER_CAN_H
#define __CONTROLLER_CAN_H

#ifdef __cplusplus
extern "C"
{
#endif

#include <stdint.h>

#include <linux/can.h>
#include <linux/can/raw.h>

#include "../subsys/libsocketcan/include/libsocketcan.h"

#define CONTROLLER_DEFINE_SEND_TIMEOUT   (0 * 1000 + 0 * 100 + 1 * 10)   /* 发送超时时间(单位ms) */
#define CONTROLLER_DEFINE_RECV_TIMEOUT   (0 * 1000 + 0 * 100 + 1 * 5)    /* 接收超时时间(单位ms) */
#define CONTROLLER_DEFINE_BUFFER_MAX_LEN (240)                           /* 数据最大长度(字节) */

/**
 * @brief Controller CAN消息接收回调函数原型, 可以通过 @ref controller_setopt 接口的 @ref CONTROLLER_OPTION_RECV_HANDLER 参数指定
 *
 * @details
 *
 * 当收到ControllerCAN的应答数据时, 通过此回调函数输出
 *
 * @param[out] handle ControllerCAN句柄
 * @param[out] frame_data 从ControllerCAN接收到的数据
 *
 * @return void
 */
typedef void (*controller_recv_handler_t)(void *handle, const struct can_frame *frame_data);

typedef struct {
    int fd;
    char *name;
    uint32_t send_timeout_ms;
    uint32_t recv_timeout_ms;
    uint32_t buffer_max_len;
    controller_recv_handler_t recv_handler;
} controller_handle_t;

typedef enum {
    CONTROLLER_OPTION_NAME,              /* 数据类型: (char *), CAN名称 */
    CONTROLLER_OPTION_SEND_TIMEOUT_MS,   /* 数据类型: (uint32_t), 网络发送超时时间(单位ms) */
    CONTROLLER_OPTION_RECV_TIMEOUT_MS,   /* 数据类型: (uint32_t), 网络接受超时时间(单位ms)*/
    CONTROLLER_OPTION_BUFFER_MAX_LEN,    /* 数据类型: (uint32_t), 每次读取数据的最大长度(字节) */
    CONTROLLER_OPTION_RECV_HANDLER,      /* 数据类型: (controller_recv_handler_t), 用户数据接受回调函数, 默认值: NULL */
    CONTROLLER_OPTION_MAX
} controller_option_t;

uint64_t controller_time(void);

/**
 * @brief 初始化
 *
 * @param[in] void
 *
 * @return
 *
 * @retval 非NULL, CONTROLLER实例
 * @retval NULL, 初始化CONTROLLER实例失败
 */
void *controller_init(void);

/**
 * @brief 配置参数
 *
 * @param[in] p_handle CONTROLLER实例句柄
 * @param[in] option 配置选项, 可查看枚举类型 @ref controller_option_t
 * @param[in] data 配置数据, 每个选项对应的数据类型可查看 @ref controller_option_t
 *
 * @return
 *
 * @retval STATE_SUCCESS, 成功
 * @retval STATE_USER_INPUT_NULL_POINTER, 参数p_handle或data为NULL
 */
int32_t controller_setopt(void *p_handle, controller_option_t option, void *data);

/**
 * @brief 断开连接
 *
 * @param[in] p_handle CONTROLLER实例句柄
 *
 * @return
 *
 * @retval STATE_SUCCESS, 成功
 * @retval STATE_USER_INPUT_NULL_POINTER, 参数p_handle为NULL
 */
int32_t controller_disconnect(void *p_handle);

/**
 * @brief 连接
 *
 * @param[in] p_handle CONTROLLER实例句柄
 * @param[in] bitrate 波特率
 *
 * @return
 *
 * @retval STATE_SUCCESS, 成功
 * @retval STATE_USER_INPUT_NULL_POINTER, 参数p_handle为NULL
 * @retval STATE_PORT_CAN_SET_BITRATE_FAILED, 配置波特率失败
 * @retval STATE_PORT_CAN_START_FAILED, 启动CAN通信失败
 */
int32_t controller_connect(void *p_handle, uint32_t bitrate);

/**
 * @brief 建立通信
 *
 * @param[in] can_name CAN名称
 * @param[in] family 地址族
 * @param[in] socktype Socket类型
 * @param[in] protocol 传输协议
 * @param[in] fd_out 描述符
 *
 * @return
 *
 * @retval STATE_SUCCESS, 成功
 * @retval STATE_USER_INPUT_NULL_POINTER, 参数can_name为NULL
 * @retval STATE_PORT_NETWORK_SOCKET_CREATE_FAILED, 创建SOCKET发生错误
 * @retval STATE_PORT_NETWORK_SOCKET_CONFIG_FAILED, 配置SOCKET发生错误
 * @retval STATE_PORT_NETWORK_SOCKET_BIND_FAILED, 绑定SOCKET发生错误
 */
int32_t controller_establish(char *can_name, int family, int socktype, int protocol, int *fd_out);

/**
 * @brief 发送数据
 *
 * @param[in] p_handle CONTROLLER实例句柄
 * @param[in] frame_data 指向发送数据的指针
 *
 * @return
 *
 * @retval STATE_SUCCESS, 成功
 * @retval STATE_USER_INPUT_NULL_POINTER, 参数p_handleh或buffer为NULL
 * @retval STATE_PORT_NETWORK_POLL_FAILED, 设置POLL失败
 * @retval STATE_CCAN_SEND_NOT_FINISHED, CAN数据发送未完成
 * @retval STATE_PORT_NETWORK_SEND_FAILED, CAN通信异常
 * @retval STATE_SYS_DEPEND_NWK_WRITE_LESSDATA, 发送数据不完整
 */
int32_t controller_send(void *p_handle, struct can_frame *frame_data);

/**
 * @brief 接收数据
 *
 * @param[in] p_handle CONTROLLER实例句柄
 *
 * @return
 *
 * @retval STATE_SUCCESS, 成功
 * @retval STATE_USER_INPUT_NULL_POINTER, 参数p_handleh或buffer为NULL
 * @retval STATE_PORT_NETWORK_POLL_FAILED, 设置POLL失败
 * @retval STATE_CCAN_RECV_NOT_FINISHED, CAN数据接收未完成
 * @retval STATE_PORT_NETWORK_RECV_FAILED, CAN通信异常
 * @retval STATE_SYS_DEPEND_NWK_READ_LESSDATA, 接收数据不完整
 */
int32_t controller_recv(void *p_handle);

/**
 * @brief 取消初始化
 *
 * @param[in] p_handle CONTROLLER实例句柄
 *
 * @return
 *
 * @retval STATE_SUCCESS, 成功
 * @retval STATE_USER_INPUT_NULL_POINTER, 参数p_handle为NULL
 */
int32_t controller_deinit(void *p_handle);

#ifdef __cplusplus
}
#endif

#endif /* __CONTROLLER_CAN_H */
